26 de agosto, 2020

Objetivo: Utilizar a linguagem Python, para prever com base nas informacoes coletadas, qual o custo do seguro saude.
Começaremos nosso projeto, importanto todas as bilbiotecas necessárias, para a realização das fases iniciais de exploração, e transformação dos dados (Data Munging).
# Importando bibliotecas, para a manipulação e exploração dos conjuntos de dados.
import numpy as np
import pandas as pd
import random
# Importando bibliotecas, para a plotagem de gráficos interativos com o plotly.
import plotly.offline as py
import plotly.graph_objs as go
import plotly.figure_factory as ff
py.init_notebook_mode(connected = False)
# Importando bibliotecas, para a plotagem de gráficos com o Seaborn e Matplotlib.
import seaborn as sns
import matplotlib as mpl
import matplotlib.pyplot as plt
# Importando classes e bibliotecas, para a etapa de pré-processamento dos dados.
from sklearn import preprocessing
# Importando classes para calcular algumas estatísticas.
from scipy.stats import kurtosis, skew
# Importando bibliotecas, para a etapa de modelagem preditiva.
from sklearn.model_selection import train_test_split
from sklearn import linear_model
from sklearn import metrics
# Definindo o nome das colunas do dataset.
names = ['idade',
'sexo',
'imc',
'filhos',
'fumante',
'regiao',
'valor']
# Carregando conjunto de dados.
data = pd.read_csv('insurance.csv', names = names, header = 0)
# Exibindo as primeiras linhas do DataFrame.
data.head()
Antes de prosseguirmos, é importante destacar a informação que cada variável representa:
| Variável | Tipo | Descrição |
|---|---|---|
| idade | int64 | Idade do benficiario primario; |
| sexo | char | Sexo do contratante; |
| imc | int64 | Indice de massa corporal; |
| filhos | char | Quantidade de filhos cobertos pelo seguro; |
| fumante | char | Se o beneficiario primario e fumante; |
| regiao | char | Regiao em que o beneficiario; |
| valor | float64 | Custo medico individual cobrado pelo saude saude; |
# Verificando as dimensões do dataset.
data.shape
# Verificando o número de NAs existentes dentro do dataset.
data.isna().sum()
Não há valores nulos dentro do conjunto de dados.
# Verificando o tipo de dados das variáveis do dataset.
data.info()
Existem 4 variaveis numerias e 3 variaveis categoricas
# Contabilizando o número de valores únicos em cada variável do dataset.
info = data.nunique().sort_values()
# Determinando o tipo de dado de cada uma das variáveis do dataset.
info = pd.DataFrame(info.values, index = info.index, columns = ['NUniques'])
# Atribuindo informações sobre o tipo de dado das variáveis ao DataFrame.
info['dtypes'] = data.dtypes
# Exibindo Dataframe.
info
Iremos definir algumas funções, para padronizar as plotagens de gráficos que criaremos.
Para fazer plotagens offline com o plotly (isto é, em ambientes como o Google Colab, Azure, Kaggle, Nteract, etc.), precisamos definir a função a seguir, e chamá-la sempre que formos gerar um gráfico.
# Definindo uma função, para plotar gráficos interativos, em um ambiente jupyter não-padrão.
def configure_plotly_browser_state():
import IPython
display(IPython.core.display.HTML('''
<script src="/static/components/requirejs/require.js"></script>
<script>
requirejs.config({
paths: {
base: '/static/base',
plotly: 'https://cdn.plot.ly/plotly-1.43.1.min.js?noext',
},
});
</script>
'''))
Os gráficos de distribuição são usados para mostrar como as variáveis são distribuídas ao longo do tempo, ajudando a identificar valores discrepantes e tendências.
# Definindo uma função, para criar gráficos de Boxplot interativos com o plotly.
def plotBoxplot(data, name = '', col = '', target = '', title = '', yaxis = '', xaxis = '', kind = 'normal',
color = ['#8783D1', '#FADF63', '#06D6A0', '#662E9B'], opacity = 0.65, template = 'plotly_white',
orientation = 'v'):
# Realizando as pré-configurações necessárias, para a plotagem do gráfico interativo.
configure_plotly_browser_state()
# Plota gráficos de um ou mais boxplots simples.
if kind == 'normal':
# Plota gráficos verticais.
if orientation == 'v':
# Definindo os dados, a cor, o nome e a transparência que serão utilizados para criar cada um dos Boxplots.
dataTrace = [
go.Box(
y = data[l],
name = l if name == '' else name,
marker = {'color': color[2], "opacity": opacity})
for l in data.columns
]
# Plota gráficos horizontais.
else:
# Definindo os dados, a cor, o nome e a transparência que serão utilizados para criar cada um dos Boxplots.
dataTrace = [
go.Box(
x = data[l],
name = l if name == '' else name,
marker = {'color': color[3], "opacity": opacity})
for l in data.columns
]
# Plota gráficos boxplot, para uma variável numérica, agrupada por uma variável categórica.
elif kind == 'groups':
# Captura os registros pertencentes a cada categoria, da variável categórica.
g = [data[data[target] == cat] for cat in data[target].cat.categories]
# Converte a primeira letra do nome de cada categoria para maiúscula.
name = [n.capitalize() for n in data[target].cat.categories]
# Plota gráficos verticais.
if orientation == 'v':
# Definindo os dados, a cor, o nome e a transparência que serão utilizados para criar cada um dos Boxplots.
dataTrace = [
go.Box(
y = g[l][col],
name = name[l],
marker = {'color': color[l], "opacity": opacity})
for l in range(0, len(g))
]
# Plota gráficos horizontais.
else:
# Definindo os dados, a cor, o nome e a transparência que serão utilizados para criar cada um dos Boxplots.
dataTrace = [
go.Box(
x = g[l][col],
name = name[l],
marker = {'color': color[l], "opacity": opacity})
for l in range(0, len(g))
]
# Defindo as configurações de layout.
layout = go.Layout (
title = title,
yaxis = {'title': yaxis},
xaxis = {'title': xaxis},
template = template
)
# Criando uma Figure, com os dados e o layout defindos.
fig = go.Figure(data = dataTrace, layout = layout)
# Plotando o Figure com o pyplot.
py.iplot(fig)
# Definindo uma função, para criar Histogramas interativos com o plotly.
def plotHist(data, col = '', target = '', title = '', yaxis = '', xaxis = '',
groups = False, color = ['#8783D1', '#FADF63', '#EF476F'], opacity = 0.65,
template = 'plotly_white'):
# Realizando as pré-configurações necessárias, para a plotagem do gráfico interativo.
configure_plotly_browser_state()
# Criando um histograma para um conjunto de dados.
if groups == False:
# Definindo os dados, a cor, e a transparência que serão utilizados para criar o Histograma.
dataTrace = go.Histogram(x = data, marker = {'color': color[2], "opacity": opacity})
# Criando um histograma para um conjunto de dados agrupado por categorias.
else:
# Captura os registros pertencentes a cada categoria, da variável categórica.
g = [data[data[target] == cat] for cat in data[target].cat.categories]
# Definindo os dados, a cor, e a transparência que serão utilizados para criar cada um dos Histogramas.
dataTrace = [
go.Histogram(
x = g[cat][col],
name = data[target].cat.categories[cat].capitalize(),
marker = {'color': color[cat], "opacity": opacity})
for cat in range(0,len(g))
]
# Defindo as configurações de layout.
layout = go.Layout(
title = title,
yaxis = {'title': yaxis},
xaxis = {'title': xaxis},
bargap = 0.05,
template = template
)
# Criando uma Figure, com os dados e o layout defindos.
fig = go.Figure(data = dataTrace, layout = layout)
# Plotando o Figure com o pyplot.
py.iplot(fig)
# Definindo uma função, para criar gráficos de Densidade interativos com o plotly.
def plotDensity(data, col = '', target = '', title = '', xaxis = '', group = False,
yaxis = 'Densidade', color = ['#8783D1', '#776a2d', '#3AAED8'],
template = 'plotly_white'):
# Realizando as pré-configurações necessárias, para a plotagem do gráfico interativo.
configure_plotly_browser_state()
# Criando um gráfico de Densidade para o conjunto de dados.
if group == False:
# Definindo os dados, a cor, e os labels que serão utilizados para criar o gráfico de Densidade.
fig = ff.create_distplot (
[data],
group_labels = [xaxis],
colors = [color[2]],
show_hist = False,
show_rug = False
)
# Criando um gráfico de Densidade para o conjunto de dados agrupado por categorias.
else:
# Captura os registros pertencentes a cada categoria, da variável categórica.
g = [data[data[target] == cat][col] for cat in data[target].cat.categories]
# Definindo os dados, a cor, e os labels que serão utilizados para criar cada um dos gráficos de Densidade.
fig = ff.create_distplot (
g,
group_labels = [n.capitalize() for n in data[target].cat.categories],
colors = color,
show_hist = False,
show_rug = False
)
# Defindo as configurações de layout.
fig.update_layout (
title_text = title,
yaxis = {"title_text": yaxis},
xaxis = {"title_text": xaxis},
template = template
)
# Plotando o Figure com o pyplot.
fig.show()
Os gráficos de comparação são usados para comparar um ou mais conjuntos de dados. Eles podem comparar itens ou mostrar diferenças ao longo do tempo.
# Definindo uma função, para criar gráficos de Barra interativos com o plotly.
def plotBar(data, col = '', target = '', title = '', yaxis = '', xaxis = '', kind = 'normal',
color = ['#8783D1', '#FADF63', '#FF9F43', '#EE6352', '#FC7A1E'], opacity = 0.65,
template = 'plotly_white', orientation = 'v'):
# Realizando as pré-configurações necessárias para a plotagem do gráfico interativo.
configure_plotly_browser_state()
# Criando gráficos na vertical.
if orientation == 'v':
# Plotando gráfico de barras simples.
if kind == 'normal':
# Definindo os dados, a cor, orientação e a transparência que serão utilizados para criar as barras.
dataTrace = go.Bar (
x = data.index,
y = data.values,
marker = {'color': color[2], "opacity": opacity},
orientation = orientation
)
# Plotando gráfico de barras agrupado por uma variável categórica.
elif kind == 'groups':
# Captura os registros pertencentes a cada categoria, da variável categórica.
g = [data[data[target] == cat] for cat in data[target].cat.categories]
# Definindo os dados, a cor, orientação e a transparência que serão utilizados para criar as barras.
dataTrace = [
go.Bar (
x = g[cat][col],
y = g[cat]['count'],
name = data[target].cat.categories[cat].capitalize(),
marker = {'color': color[cat], "opacity": opacity},
orientation = orientation)
for cat in range(0,len(g))
]
# Criando gráficos na horizontal.
else:
# Plotando gráfico de barras simples.
if kind == 'normal':
# Definindo os dados, a cor, orientação e a transparência que serão utilizados para criar as barras.
dataTrace = go.Bar(
x = data.values,
y = data.index,
marker = {'color': color[3], "opacity": opacity},
orientation = orientation
)
# Plotando gráfico de barras agrupado por uma variável categórica.
elif kind == 'groups':
# Captura os registros pertencentes a cada categoria, da variável categórica.
g = [data[data[target] == cat] for cat in data[target].cat.categories]
# Definindo os dados, a cor, orientação e a transparência que serão utilizados para criar as barras.
dataTrace = [
go.Bar(
x = g[cat]['count'],
y = g[cat][col],
name = data[target].cat.categories[cat].capitalize(),
marker = {'color': color[cat], "opacity": opacity},
orientation = orientation)
for cat in range(0,len(g))
]
# Defindo as configurações de layout.
layout = go.Layout(
title = title,
yaxis = {'title': yaxis},
xaxis = {'title': xaxis},
template = template
)
# Criando uma Figure, com os dados e o layout defindos.
fig = go.Figure(data = dataTrace, layout = layout)
# Definindo que as barras devem ser dispostas uma ao lado da outra caso estejam agrupadas por categoria.
# Para criar Stacked Bars, utilize: 'stack'.
fig.update_layout(barmode = 'group')
# Plotando o Figure com o pyplot.
fig.show()
Os gráficos de composição são usados para exibir partes de um todo e mudar ao longo do tempo.
# Definindo uma função, para realizar a plotagem de gráficos de pizza.
def plotPie(data, title = ''):
# Realizando as pré-configurações necessárias, para a plotagem do gráfico interativo.
configure_plotly_browser_state()
# Defindo as configurações de layout.
layout = go.Layout (
title = title
)
# Criando uma Figure, com os dados e o layout defindos.
fig = go.Figure (
data = [
go.Pie(
labels = [i[0].upper() + i[1:] for i in dataCounts.index],
values = dataCounts.values,
hole = .1)
],
layout = layout
)
# Adicionando uma borda branca em cada uma das fatias da pizza.
fig.update_traces (
marker = dict (
line = dict (
color = '#FFFFFF',
width = 1
)
)
)
# Plotando a Figure com o pyplot.
fig.show()
Os gráficos de relacionamento são usados para mostrar uma conexão ou correlação entre duas ou mais variáveis.
# Definindo uma função, para realizar a plotagem de gráficos de correlação.
def plotCorr(corr, figsize = (18, 18), cmap = 'Blues', title = 'Gráfico de Correlação entre as variáveis do Data Frame'):
# Criando uma máscara, com as mesmas dimensões da matriz de correlação.
mask = np.zeros_like(corr)
# Selecionando a matriz triangular inferior da máscara.
mask[np.triu_indices_from(mask)] = True
# Definindo as dimensões do gráfico a ser plotado.
_, ax = plt.subplots(figsize = figsize)
# Criando o gráfico Heatmap.
ax = sns.heatmap (
data = corr,
mask = mask,
vmax = .3,
linewidths = .5,
square = True,
cmap = cmap,
annot = True
)
# Definindo o título do gráfico.
ax = ax.set_title(title)
Criaremos uma função, para padronizar as estatísticas que calcularemos, em cada uma das variáveis a serem estudadas.
# Definindo uma função, para gerar um dataframe, com as estatísticas de uma variável do dataset.
def varStats(col, data, target = ''):
if target == '':
# Criando um dataframe, com as estatísticas da variável especificada.
stats = pd.DataFrame({
'min' : data[col].min(),
'Q1' : data[col].quantile(.25),
'Median': data[col].median(),
'Mean' : data[col].mean(),
'Q3' : data[col].quantile(.75),
'SD' : data[col].std(),
'Sk' : skew(data[col]),
'Ck' : kurtosis(data[col])
}, index = [col])
else:
# Criando um dataframe, com as estatísticas da variável especificada, agrupada pela variável target.
stats = pd.concat([
data[[col, target]].groupby(target).min(),
data[[col, target]].groupby(target).quantile(.25),
data[[col, target]].groupby(target).median(),
data[[col, target]].groupby(target).mean(),
data[[col, target]].groupby(target).quantile(.75),
data[[col, target]].groupby(target).std(),
data[[col, target]].groupby(target).skew(),
data[[col, target]].groupby(target).apply(lambda group: kurtosis(group)[0])
], axis = 1)
# Renomeando as colunas do DataFrame.
stats.columns = ['min', 'Q1', 'Median', 'Mean', 'Q3', 'SD', 'Sk', 'Ck']
# Retornando os resultados obtidos.
return stats
O coeficente de Assimetria (Skewness), indica como os dados estão distribuídos, e para interpretar seu resultado podemos olhar a tabela a seguir:
| Índice de Assimetria | Descrição |
|---|---|
| SK ≈ 0 | Os dados são simétricos. Tanto a cauda do lado direito, quanto a do lado esquerdo da função densidade de probabilidade, são iguais; |
| SK < 0 | A assimetria é negativa. A cauda do lado esquerdo da função densidade de probabilidade, é maior que a do lado direito e; |
| SK > 0 | A assimetria é positiva. A cauda do lado direito da função densidade de probabilidade, é maior que a do lado esquerdo. |
O coeficiente de Curtose (Kurtosis), é uma medida que caracteriza o achatamento da curva da função de distribuição, e para interpretar seu resultado, podemos olhar a tabela a seguir:
| Índice de Curtose | Descrição |
|---|---|
| CK ≈ 0 | A distribuição é normal, e é chamada de Curtose Mesocúrtica; |
| CK < 0 | A Cauda é mais leve que a normal. Para um coeficiente de Curtose negativo, tem-se uma Curtose Platicúrtica e; |
| CK > 0 | A Cauda é mais pesada que a normal. Para um coeficiente de Curtose positivo, tem-se uma Curtose Leptocúrtica. |
# Definindo o nome da variável a ser analisada.
col = 'idade'
# Definindo a descrição da variável nos gráficos.
label = 'Idade do beneficiario'
# Contabilizando a frequência absoluta de cada categoria presente na variável especificada.
dataCounts = data[col].value_counts()
# Plotando um gráfico de barras para as variáveis especificadas.
plotBar (
data = dataCounts,
title = 'Frequência absoluta das categorias da Feature ' + col,
yaxis = label,
xaxis = 'Frequência Absoluta',
orientation = 'v'
)
Percebe-se que um grande numero de beneficiarios tem menos de 20 anos.
# Criando um gráfico de Densidade para a variável especificada.
plotDensity (
data = data[col],
title = 'Gráfico de Densidade para a variável ' + col,
xaxis = label
)
# Plotando um gráfico de boxplot para as variável especificada.
plotBoxplot (
data = data[[col]],
title = 'Boxplot para a variável ' + col,
xaxis = 'Variável',
name = label
)
Nao foi registrado nenhum outlier
# Calculando algumas estatísticas para a variável especificada.
varStats(col, data = data)
Destacamos que:
# Definindo o nome da variável a ser analisada.
col = 'imc'
# Definindo a descrição da variável nos gráficos.
label = 'IMC'
# Contabilizando a frequência absoluta de cada categoria presente na variável especificada.
dataCounts = data[col].value_counts()
# Plotando um gráfico de histograma para a variável especificada.
plotHist (
data = data[col],
title = 'Histograma para a variável ' + col,
xaxis = label,
yaxis = 'Frequência Absoluta'
)
A medicina demonstrou que o controle de peso tem um papel importante no tratamento e desenvolvimento de uma nova vida com diabetes. Em particular, a prevenção da obesidade e do sobrepeso também reduz o risco de outras doenças crônicas perigosas, como a pressão arterial alta.
O índice de massa corporal (IMC) ou Body mass index (BMI) é um valor especial que mostra se o peso de uma pessoa está em um nível adequado ou não. Este valor se calcula em função da relação entre o peso e a altura, de acordo com a fórmula:
$IMC (kg / m^2) = Peso (kg) / [Altura (m)]^2$
De modo geral, em adultos, o IMC normal fica entre 18,5 a 23 $kg / m^2$. Quanto mais alto seja o número, mais peso sobra, e mais obeso é e deve começar a emagrecer de forma razoável.
A partir de uma análise da fórmula utilizada para calcular o IMC, podemos concluir que os registros em que seu valor é 0 são erros.
# Criando um gráfico de Densidade para a variável especificada.
plotDensity (
data = data[col],
title = 'Gráfico de Densidade para a variável ' + col,
xaxis = label
)
# Plotando um gráfico de boxplot para a variável especificada.
plotBoxplot (
data = data[[col]],
title = 'Boxplot para a variável ' + col,
xaxis = 'Variável',
name = label
)
# Calculando algumas estatísticas para a variável especificada.
varStats(col, data = data)
Destacamos que:
# Definindo o nome da variável a ser analisada.
col = 'filhos'
# Definindo a descrição da variável nos gráficos.
label = 'Quantidade de filhos'
# Contabilizando a frequência absoluta de cada categoria presente na variável especificada.
dataCounts = data[col].value_counts()
# Plotando um gráfico de histograma para a variável especificada.
plotHist (
data = data[col],
title = 'Histograma para a variável ' + col,
xaxis = label,
yaxis = 'Frequência Absoluta'
)
# Definindo o nome da variável a ser analisada.
col = 'sexo'
# Definindo a descrição da variável nos gráficos.
label = 'Sexo'
# Contabilizando a frequência absoluta de cada categoria presente na variável especificada.
dataCounts = data[col].value_counts()
# Plotando um gráfico de histograma para a variável especificada.
plotHist (
data = data[col],
title = 'Histograma para a variável ' + col,
xaxis = label,
yaxis = 'Frequência Absoluta'
)
# Plotando um gráfico de pizza para a variável especificada.
plotPie (
data = dataCounts,
title = 'Frequência relativa das categorias da feature ' + col
)
Dataset balanceado para a variavel idade
# Definindo o nome da variável a ser analisada.
col = 'fumante'
# Definindo a descrição da variável nos gráficos.
label = 'Fumante'
# Contabilizando a frequência absoluta de cada categoria presente na variável especificada.
dataCounts = data[col].value_counts()
# Plotando um gráfico de histograma para a variável especificada.
plotHist (
data = data[col],
title = 'Histograma para a variável ' + col,
xaxis = label,
yaxis = 'Frequência Absoluta'
)
MAior proporcao de beneficiarios nao fumantes
# Plotando um gráfico de pizza para a variável especificada.
plotPie (
data = dataCounts,
title = 'Frequência relativa das categorias da feature ' + col
)
# Definindo o nome da variável a ser analisada.
col = 'regiao'
# Definindo a descrição da variável nos gráficos.
label = 'Regiao'
# Contabilizando a frequência absoluta de cada categoria presente na variável especificada.
dataCounts = data[col].value_counts()
# Plotando um gráfico de barras para as variável especificada.
plotBar (
data = dataCounts,
title = 'Frequência absoluta das categorias da Feature ' + col,
yaxis = 'Frequência Absoluta',
xaxis = label
)
# Plotando um gráfico de pizza para a variável especificada.
plotPie (
data = dataCounts,
title = 'Frequência relativa das categorias da feature ' + col
)
Uma pequena maioria contabilizada na regiao sudoeste.
# Definindo o nome da variável a ser analisada.
col = 'valor'
# Definindo a descrição da variável nos gráficos.
label = 'Valor'
# Contabilizando a frequência absoluta de cada categoria presente na variável especificada.
dataCounts = data[col].value_counts()
# Plotando um gráfico de histograma para a variável especificada.
plotHist (
data = data[col],
title = 'Histograma para a variável ' + col,
xaxis = label,
yaxis = 'Frequência Absoluta'
)
Grande parte dos registros se encontram ate o valor de 14K
# Criando um gráfico de Densidade para a variável especificada.
plotDensity (
data = data[col],
title = 'Gráfico de Densidade para a variável ' + col,
xaxis = label
)
# Plotando um gráfico de boxplot para as variáveis especificadas.
plotBoxplot (
data = data[[col]],
title = 'Boxplot para a variável ' + col,
xaxis = 'Variável',
name = label
)
# Calculando algumas estatísticas para a variável especificada.
varStats(col, data = data)
Destacamos que:
#encoding a coluna "sexo":
data.replace({'sexo':{'male':0, 'female':1}},inplace = True)
#encoding a coluna "fumante":
data.replace({'fumante':{'yes':0, 'no':1}},inplace = True)
#encoding a coluna "regiao":
data.replace({'regiao':{'southeast':0,'northwest':1,'southwest':2,'northeast':3,}},inplace = True)
data.head()
Nesta etapa, iremos segmentar os registros em dados de treino e de teste.
# Criando conjunto de dados de treino e de teste.
trainFeatures, testFeatures, trainTarget, testTarget = train_test_split (
data.drop('valor', axis = 1), data['valor'], test_size = 0.20
)
# Verificando as novas dimensões do DataFrame preditor de treino.
trainFeatures.shape
# Verificando as novas dimensões do DataFrame preditor de teste.
testFeatures.shape
# Verificando a dimensao da variavel alvo no treino
trainTarget.shape
# Verificando a dimensao da variavel alvo no teste
testTarget.shape
#iniciando o modelo
model = linear_model.LinearRegression()
#treinando o modelo com os dados de treino
model.fit(trainFeatures.values,trainTarget)
#avaliando os valores previstos com os dados de treino
pred_train = model.predict(trainFeatures.values)
# R2Score dos dados de treino:
r2s_train = metrics.r2_score(trainTarget, pred_train)
print("R2Score:", r2s_train)
#avaliando o modelo com os dados de teste
pred_test = model.predict(testFeatures.values)
# R2Score dos dados de teste:
r2s_test = metrics.r2_score(testTarget, pred_test)
print("R-squared value:", r2s_test)
# Produz a matriz com os novos dados de entrada para a previsão
IDADE = 60
SEXO = 1
BMI = 23.001
FILHOS = 2
FUMANTE = 1
REGIAO = 3
# Lista com os valores das variáveis
dados_nova_casa = [IDADE, SEXO, BMI, FILHOS, FUMANTE, REGIAO]
# Reshape
Xp = np.array(dados_nova_casa).reshape(1, -1)
M = model.predict(Xp)
# Previsão
print("O custo provavel do seguro sera: $", M[0])